package main

import (
	"fmt"
)

type Painter interface {
	Paint()
}

type Clicker interface {
	Click()
}

// 结构体嵌入
type Widget struct {
	X, Y int
}

type Label struct {
	Widget
	Text string
}

func (Label Label) Paint() {
	fmt.Printf("%p:Label.Paint(%q) \n", &Label, Label.Text)
}

type Button struct {
	Label // Embedding(delegation)
}

// 因为这个接口可以通过 label 的嵌入带入到新的结构体中
// 所有, 可以的 button 中可以重载这个接口的方法
func (b Button) Paint() { // override
	fmt.Printf("Button.Paint(%s)", b.Text)
}

func (b Button) Click() {
	fmt.Printf("Button.Click(%s)\n", b.Text)
}

type ListBox struct {
	Widget          // Embedding(delegation)
	Texts  []string // aggregation
	Index  int      // aggregation
}

func (lb ListBox) Paint() {
	fmt.Printf("ListBox.Paint(%q) \n", lb.Texts)
}

func (lb ListBox) Click() {
	fmt.Printf("ListBox.Click(%q) \n", lb.Texts)
}

func main() {
	label := Label{Widget{50, 25}, "label"}
	button1 := Button{Label{Widget{10, 10}, "OK"}}
	button2 := Button{Label{Widget{50, 70}, "Cancel"}}
	listBox := ListBox{
		Widget: Widget{10, 40},
		Texts:  []string{"AL", "AK", "AZ", "AR"},
		Index:  0,
	}

	for _, painter := range []Painter{label, button1, button2, listBox} {
		painter.Paint()
	}

	for _, widget := range []interface{}{label, button1, button2, listBox} {
		widget.(Painter).Paint()
		if clicker, ok := widget.(Clicker); ok {
			clicker.Click()
		}
		fmt.Println() // print a empty line
	}
}
